﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using UL360Admin.Survey.Models;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using MigraDoc.DocumentObjectModel;
using MigraDoc.DocumentObjectModel.Tables;
using MigraDoc.DocumentObjectModel.Shapes;
using MigraDoc.Rendering;
using System.IO;
using UL360DataNET40;
using UL360Admin.Survey.ReportLanguages;
using UL360SurveyCommon.Models;
using UL360SurveyCommon;
using System.Net.Mail;
using System.Configuration;
using System.Net.Mime;

namespace UL360Admin.Survey.Utils
{
    public static class ReportsUtil
    {
        #region Properties
        //Font settings
        private static string defaultFontFamily = "Verdana";
        private static int defaultFontSize = 10;
        private static int defaultHeading1FontSize = 20;
        private static int defaultHeading2FontSize = 14;
        private static int defaultHeading3FontSize = 10;
        private static Color defaultFontColor = Colors.Black;
        private static Color headingColor = Color.Parse("0xA2AD00");

        //Sizes
        private static double sideMargins = XUnit.FromCentimeter(3).Point;
        private static double topMargins = XUnit.FromCentimeter(2.5).Point;
        private static double heading1Margins = XUnit.FromCentimeter(0.5).Point;
        #endregion

        #region CreateReport
        public static ReportResponse CreateReport(int formType, int courseId, bool sendmail)
        {
            //Variables to get and set course information
            Kurstillfalle course;

            //Variables to get and set survey report information such as question texts and answer values and texts
            int formId;
            ICollection<SurveyAnswerScale> scaleAnswers;
            ICollection<SurveyAnswerText> textAnswers;
            ICollection<SurveyQuestionText> scaleQuestionTexts;
            ICollection<SurveyQuestionText> textQuestionTexts;
            int answerers = 0;
            List<double> totalValue = new List<double>();

            //Get language id for course (Swedish is default language)
            int languageId = 1;
            int.TryParse(System.Configuration.ConfigurationManager.AppSettings["SwedishLanguageId"], out languageId);

            using (var db = new UL360Entities())
            {
                //Get course, course name and dates
                course = db.Kurstillfalles.Include("Handledares").Include("Handledare").Where(c => c.kursid == courseId).DefaultIfEmpty(null).First();

                //Get language for course
                if (sendmail == true)
                {
                    languageId = course.sprakid;
                }

                //Get survey form for course
                formId = db.SurveyForms.Where(f => f.SurveyType == formType && f.DateCreated <= course.slutdatum).OrderByDescending(f => f.DateCreated).First().SurveyFormId;

                //Get questions texts for form id and question type
                scaleQuestionTexts = db.SurveyForms.Where(f => f.SurveyFormId == formId).SelectMany(fq => fq.SurveyQuestions).OrderBy(q => q.Order).Where(type => type.QuestionType == 0).SelectMany(qt => qt.SurveyQuestionTexts).Where(l => l.fk_SprakId == languageId).ToList();
                textQuestionTexts = db.SurveyForms.Where(f => f.SurveyFormId == formId).SelectMany(fq => fq.SurveyQuestions).OrderBy(q => q.Order).Where(type => type.QuestionType == 1).SelectMany(qt => qt.SurveyQuestionTexts).Where(l => l.fk_SprakId == languageId).ToList();

                //Get scale & text answers by course and form id
                scaleAnswers = course.SurveyAnswerScales.Where(q => q.fk_SurveyFormId == formId && q.fk_KursId == courseId).ToList();
                textAnswers = course.SurveyAnswerTexts.Where(q => q.fk_SurveyFormId == formId && q.fk_KursId == courseId).ToList();
            }

            //Get PDF-report static strings by correct language
            ILanguage templateLanguage = null;
            if (languageId == Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["SwedishLanguageId"]))
            {
                templateLanguage = new Swedish();
            }
            else if (languageId == Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["EnglishLanguageId"]))
            {
                templateLanguage = new English();
            }
            else if (languageId == Convert.ToInt16(System.Configuration.ConfigurationManager.AppSettings["NorwegianLanguageId"]))
            {
                templateLanguage = new Norwegian();
            }

            List<PDFScaleQuestionAnswer> scaleQuestionAnswers = new List<PDFScaleQuestionAnswer>();
            List<PDFTextQuestionAnswer> textQuestionAnswers = new List<PDFTextQuestionAnswer>();

            #region scale questions and answers
            //Get question texts and answers for each question
            foreach (SurveyQuestionText question in scaleQuestionTexts)
            {
                List<int> answerValues = new List<int>();
                Dictionary<int, int> distribution = new Dictionary<int, int>();

                if (scaleAnswers.Count > 0)
                {
                    //Get all answer values for the specific question
                    foreach (var answer in scaleAnswers.Where(sq => sq.fk_SurveyQuestionId == question.fk_SurveyQuestionId).ToList())
                    {
                        answerValues.Add(answer.ScaleAnswer);
                    }
                }

                //Count distribution of answers
                for (int i = 0; i < 10; i++)
                {
                    int key = i;
                    int value = 0;

                    if (answerValues.Contains(i))
                    {
                        value = answerValues.FindAll(a => a == i).Count;
                    }

                    distribution.Add(key, value);
                }

                answerers = Convert.ToInt16(answerValues.Count());
                
                answerValues = answerValues.Where(a => a != 0).ToList();

                //Number of answers
                double length = answerValues.Count();

                //Sum of all answer values for the question
                double sum = answerValues.Sum();

                //Set number of answerers and total course average value for this survey
                double average = sum / length;

                //If all anwers was "dont know"
                if (double.IsNaN(average))
                {
                    average = 0;
                }

                scaleQuestionAnswers.Add(new PDFScaleQuestionAnswer
                {
                    Question = question.Question.ToString(),
                    Average = average,
                    Distribution = distribution
                });

                //Add average value of all answers for this question
                totalValue.Add(average);
            }
#endregion

            #region text questions and answers
            //Get question texts and text answers for each question
            foreach (SurveyQuestionText question in textQuestionTexts)
            {
                //List that holds the answer texts
                
                List<string> answerTexts = new List<string>();

                //Get text answers and questions only if text answers exist
                if (textAnswers.Where(sq => sq.fk_SurveyQuestionId == question.fk_SurveyQuestionId).ToList().Count > 0)
                {
                    //Get all answer values for the specific question
                    foreach (var answer in textAnswers.Where(sq => sq.fk_SurveyQuestionId == question.fk_SurveyQuestionId).ToList())
                    {
                        answerTexts.Add(answer.TextAnswer);
                    }

                    //Set question with answers
                    textQuestionAnswers.Add(new PDFTextQuestionAnswer
                    {
                        Question = question.Question,
                        TextAnswer = answerTexts,
                    });
                }

            }
            #endregion

            //Create response
            ReportResponse reportResponse = new ReportResponse
            {
                Status = 0,
                ReportContent = Convert.ToBase64String(GeneratePDF(new PDFData
                {
                    Course = course, 
                    FormType = (SurveyType)formType,
                    ScaleQuestionAnswers = scaleQuestionAnswers, 
                    TextQuestionAnswers = textQuestionAnswers,
                    ScaleAnswers = scaleAnswers, 
                    TextAnswers = textAnswers,
                    ScaleQuestionTexts = scaleQuestionTexts, 
                    TextQuestionTexts = textQuestionTexts, 
                    TemplateLanguage = templateLanguage,
                    NumberOfAnswerers = answerers,
                    TotalCourseAverage = Math.Round(totalValue.Sum() / scaleQuestionAnswers.Count, 2)
                })),
            };

            return reportResponse;
        }
        #endregion

        #region Generate PDF
        public static byte[] GeneratePDF(PDFData pdfData)
        {
            // Create a new PDF document
            Document document = new Document();

            //First page of document
            GenerateFirstPage(document, pdfData);

            //Answer data in document (if any answers)
            if (pdfData.NumberOfAnswerers > 0)
            {
                if (pdfData.ScaleQuestionAnswers.Count > 0)
                {
                    GenerateScaleAnswerPages(document, pdfData);
                }

                if (pdfData.TextQuestionAnswers.Count > 0)
                {
                    GenerateTextAnswerPages(document, pdfData);
                }
            }

            // Create a renderer and prepare (=layout) the document
            PdfDocumentRenderer docRenderer = new PdfDocumentRenderer();
            docRenderer.Document = document;
            docRenderer.RenderDocument();

            // Save the document...
            MemoryStream memory = new MemoryStream();

            docRenderer.PdfDocument.Save(memory, false);

            return memory.ToArray();
        }
        #endregion

        #region Generate first page for PDF
        public static void GenerateFirstPage(Document document, PDFData pdfData)
        {
            Section sec = document.AddSection();

            // Add a single paragraph with some text and format information.
            Paragraph para = sec.AddParagraph();

            //Paragraph style
            para.Format.Alignment = ParagraphAlignment.Left;
            para.Format.Font.Name = defaultFontFamily;
            para.Format.Font.Size = defaultFontSize;
            para.Format.Font.Color = defaultFontColor;

            if (pdfData.FormType.Equals(SurveyType.OriginalCourse))
            {
                //Pdf title
                para.AddFormattedText(pdfData.TemplateLanguage.PdfTitle, new Font { Size = defaultHeading1FontSize, Bold = true, Color = headingColor });
                para.AddLineBreak();
                para.AddLineBreak();
                para.AddLineBreak();
            }
            else if (pdfData.FormType.Equals(SurveyType.ExtendedCourse))
            {
                //Extended course (part 2) Pdf title
                para.AddFormattedText(pdfData.TemplateLanguage.ExtPdfTitle, new Font { Size = defaultHeading1FontSize, Bold = true, Color = headingColor });
                para.AddLineBreak();
                para.AddLineBreak();
                para.AddLineBreak();
            }

            //Summary for report
            //Get course name
            para.AddFormattedText(pdfData.TemplateLanguage.CourseName, new Font { Size = defaultFontSize, Bold = true });
            para.AddText(pdfData.Course.organisation);
            para.AddLineBreak();

            if (pdfData.FormType.Equals(SurveyType.OriginalCourse))
            {
                //Get course dates
                para.AddFormattedText(pdfData.TemplateLanguage.CourseDate, new Font { Size = defaultFontSize, Bold = true });
                para.AddText(pdfData.Course.startdatum.ToShortDateString() + " -- " + pdfData.Course.slutdatum.ToShortDateString());
                para.AddLineBreak();
            }
            else if (pdfData.FormType.Equals(SurveyType.ExtendedCourse))
            {
                //Get course dates
                para.AddFormattedText(pdfData.TemplateLanguage.CourseDate, new Font { Size = defaultFontSize, Bold = true });
                para.AddText(((DateTime)pdfData.Course.DatumFordjupningsdag).ToShortDateString());
                para.AddLineBreak();
            }

            //Get tutors
            string allTutors;
            para.AddFormattedText(pdfData.TemplateLanguage.Tutor, new Font { Size = defaultFontSize, Bold = true });
            if (pdfData.Course.Handledare != null && pdfData.Course.Handledares.Count > 0)
            {
                allTutors = pdfData.Course.Handledare.fornamn + " " + pdfData.Course.Handledare.efternamn + ", " + string.Join(", ", pdfData.Course.Handledares.Where(t => t.handledarid != pdfData.Course.Handledare.handledarid).Select(h => h.fornamn + " " + h.efternamn).ToList());
            }
            else if (pdfData.Course.Handledare != null && pdfData.Course.Handledares.Count <= 0)
            {
                allTutors = pdfData.Course.Handledare.fornamn + " " + pdfData.Course.Handledare.efternamn;
            }
            else
            {
                allTutors = string.Join(", ", pdfData.Course.Handledares.Select(h => h.fornamn + " " + h.efternamn).ToList());
            }
            para.AddText(allTutors);
            para.AddLineBreak();


            //Get report created date
            para.AddFormattedText(pdfData.TemplateLanguage.ReportCreatedDateTitle, new Font { Size = defaultFontSize, Bold = true });
            para.AddText(DateTime.Now.ToShortDateString());
            para.AddLineBreak();

            //Add footer to first page
            if (pdfData.FormType.Equals(SurveyType.OriginalCourse))
            {
                Paragraph footer = sec.AddParagraph();
                footer.AddText(pdfData.TemplateLanguage.FooterText);
                footer.Format.Alignment = ParagraphAlignment.Center;
                footer.Format.SpaceBefore = Unit.FromCentimeter(19.0);
            }
            else if (pdfData.FormType.Equals(SurveyType.ExtendedCourse))
            {
                Paragraph footer = sec.AddParagraph();
                footer.AddText(pdfData.TemplateLanguage.ExtFooterText);
                footer.Format.Alignment = ParagraphAlignment.Center;
                footer.Format.SpaceBefore = Unit.FromCentimeter(19.0);
            }

            //Add report summary metrics if any participant has answered the survey
            if (pdfData.NumberOfAnswerers < 1)
            {
                para.AddFormattedText(pdfData.TemplateLanguage.NumberOfAnswers, new Font { Size = defaultFontSize, Bold = true });
                para.AddText(pdfData.TemplateLanguage.NoAnswers); //Tyvärr har ingen deltagare har svarat på enkäten
                para.AddLineBreak();
            }
            else
            {
                para.AddFormattedText(pdfData.TemplateLanguage.NumberOfAnswers, new Font { Size = defaultFontSize, Bold = true });
                para.AddText(pdfData.NumberOfAnswerers.ToString());
                para.AddLineBreak();

                //Add average value on the course as a whole
                para.AddFormattedText(pdfData.TemplateLanguage.AverageTitle, new Font { Size = defaultFontSize, Bold = true });
                para.AddText(pdfData.TotalCourseAverage.ToString());
            }
        }
        #endregion

        #region Generate scale answers for PDF
        public static void GenerateScaleAnswerPages(Document document, PDFData pdfData)
        {
            Section sec = document.AddSection();

            // Add a single paragraph with some text and format information.
            Paragraph para = sec.AddParagraph();

            //Paragraph style
            para.Format.Alignment = ParagraphAlignment.Left;
            para.Format.Font.Name = defaultFontFamily;
            para.Format.Font.Size = defaultFontSize;
            para.Format.Font.Color = defaultFontColor;

            //Scale answers title
                para.AddFormattedText(pdfData.TemplateLanguage.ScaleQuestionsTitle, new Font { Size = defaultHeading2FontSize, Bold = true });
                para.AddLineBreak();
                para.AddLineBreak();
                para.AddLineBreak();

            //Question number
            int i = 1;

            //Scale questions and answers
            foreach (PDFScaleQuestionAnswer answer in pdfData.ScaleQuestionAnswers)
            {
                // Add a single paragraph with some text and format information.
                para = sec.AddParagraph();

                //Paragraph style
                para.Format.Alignment = ParagraphAlignment.Left;
                para.Format.Font.Name = defaultFontFamily;
                para.Format.Font.Size = defaultFontSize;
                para.Format.Font.Color = defaultFontColor;

                //Add question text
                para.AddFormattedText(i.ToString() + ". " + answer.Question, new Font { Size = defaultHeading3FontSize, Bold = true });
                para.AddLineBreak();
                para.AddLineBreak();

                //Add average answer
                para.AddFormattedText(pdfData.TemplateLanguage.AverageAnswerTitle, new Font { Bold = true });
                para.AddFormattedText(!double.IsNaN(answer.Average) ? Math.Round(answer.Average, 2).ToString() : "0", new Font { Size = defaultFontSize });
                para.AddLineBreak();
                para.AddLineBreak();

                //Add spread title and data
                para.AddFormattedText(pdfData.TemplateLanguage.SpreadTitle, new Font { Bold = true });
                para.AddLineBreak();

                Table table = new Table();

                table.AddColumn().Width = Unit.FromCentimeter(2.5);

                //Adding columns depending if there is any answer for a particular value
                for (int x = 0; x < answer.Distribution.Count; x++ )
                {
                    if (answer.Distribution.ElementAt(x).Value > 0)
                    {
                        //Setting column width depending on content (text or number)
                        if (answer.Distribution.ElementAt(x).Key == 0)
                        {
                            table.AddColumn().Width = Unit.FromCentimeter(2.5);
                        }
                        else {
                            table.AddColumn().Width = Unit.FromCentimeter(1.2);
                        }
                    }
                }

                Row tablerow1 = table.AddRow();
                Row tablerow2 = table.AddRow();

                tablerow1.Borders.Bottom = new Border { Color = Colors.LightGray, Width = 1};

                tablerow1.Cells[0].AddParagraph(pdfData.TemplateLanguage.AnswerValue);
                tablerow2.Cells[0].AddParagraph(pdfData.TemplateLanguage.NumberOfValueAnswers);

                int n = 1;

                //Add spread answers
                foreach (KeyValuePair<int, int> spreadItem in answer.Distribution)
                {
                    if (spreadItem.Value > 0)
                    {
                        string key = spreadItem.Key.ToString();

                        if (key == "0")
                        {
                            //Replace 0 value with string "don't know"
                            key = pdfData.TemplateLanguage.DontKnowAnswer;
                        }

                        //Add value
                        tablerow1.Cells[n].AddParagraph().AddFormattedText(key, new Font { Size = defaultFontSize });
                        //Add number of answers on that value
                        tablerow2.Cells[n].AddParagraph().AddFormattedText(spreadItem.Value.ToString(), new Font { Size = defaultFontSize });

                        n++;
                    }
                }
                sec.Add(table);

                para = sec.AddParagraph();
                para.AddLineBreak();
                para.AddLineBreak();

                i++;
            }
        }
        #endregion

        #region Generate text answers for PDF
        public static void GenerateTextAnswerPages(Document document, PDFData pdfData)
        {
            Section sec = document.AddSection();

            // Add a single paragraph with some text and format information.
            Paragraph para = sec.AddParagraph();

            //Paragraph style
            para.Format.Alignment = ParagraphAlignment.Left;
            para.Format.Font.Name = defaultFontFamily;
            para.Format.Font.Size = defaultFontSize;
            para.Format.Font.Color = defaultFontColor;

            //Free text answers title
            para.AddFormattedText(pdfData.TemplateLanguage.TextQuestionsTitle, new Font { Size = defaultHeading2FontSize, Bold = true });
            para.AddLineBreak();
            para.AddLineBreak();
            para.AddLineBreak();

            //Question number
            int i = 1;

            //Scale questions and answers
            foreach (PDFTextQuestionAnswer answer in pdfData.TextQuestionAnswers)
            {
                // Add a single paragraph with some text and format information.
                para = sec.AddParagraph();

                //Paragraph style
                para.Format.Alignment = ParagraphAlignment.Left;
                para.Format.Font.Name = defaultFontFamily;
                para.Format.Font.Size = defaultFontSize;
                para.Format.Font.Color = defaultFontColor;

                //Add question text
                para.AddFormattedText(i.ToString() + ". " + answer.Question, new Font { Size = defaultHeading3FontSize, Bold = true });
                para.AddLineBreak();
                para.AddLineBreak();

                //Adding text answer
                for (int x = 0; x < answer.TextAnswer.Count; x++ )
                {
                   para.AddFormattedText("\"" + answer.TextAnswer[x] + "\"", new Font { Size = defaultFontSize });
                   para.AddLineBreak();
                   para.AddLineBreak();
                }

                i++;
            }
        }
        #endregion

        #region MailReport
        public static MailReportResponse MailReport(string reportContent, List<MailTemplate> templates, int courseId)
        {
            //Instantialize new course
            Kurstillfalle course = null;

            //Get course from db along with tutors
            using (var db = new UL360Entities())
            {
                course = db.Kurstillfalles.Include("Handledare.aspnet_Membership").Include("Handledares.aspnet_Membership").Where(c => c.kursid == courseId).DefaultIfEmpty(null).First();
            }

            //New tutors list
            List<Handledare> tutors = course.Handledares.ToList();

            //Add main tutor to tutors list if not present
            if(course.Handledare != null && tutors.Where(c => c.handledarid == course.Handledare.handledarid).Count() <= 0)
            {
                tutors.Add(course.Handledare);
            }

            //Chose template from language
            MailTemplate template = templates.Where(t => t.languageId == course.sprakid).First();

            //Set values for SMTP
            string smtpHost = ConfigurationManager.AppSettings["SMTPHost"];
            int smtpPort = 25;
            int.TryParse(ConfigurationManager.AppSettings["SMTPPort"], out smtpPort);
            string smtpUser = ConfigurationManager.AppSettings["SMTPUser"];
            string smtpPassword = ConfigurationManager.AppSettings["SMTPPassword"];
            string fromAddress = ConfigurationManager.AppSettings["FromAddress"];

            //Initialize smtp-client
            SmtpClient smtp = InitializeSMTPClient(smtpHost, smtpPort, smtpUser, smtpPassword);

            ICollection<string> couldNotSendTo = new List<string>();

            //Loop through all tutors and mail them
            foreach (Handledare tutor in tutors)
            {
                //Create new mailsmessage from template
                MailMessage mail = new MailMessage(fromAddress, tutor.aspnet_Membership.Email);

                //Replace values in subject with values for current participant in loop
                mail.Subject = MailTemplate.InsertTutorValues(template.Subject, tutor);
                    
                //Replace values in template with values for current participant in loop
                string message = MailTemplate.InsertTutorValues(template.Message, tutor);

                //Replace values in template with values for current course in loop
                message = MailTemplate.InsertCourseValues(message, course);

                //Set wether mailbody is HTML
                mail.IsBodyHtml = template.IsHtml;
                
                //If mailbody is HTML, replace values with html values
                if (mail.IsBodyHtml)
                {
                    message = message.Replace("\n", "<br />").Replace("\r\n", "<br />");
                }

                //Set mailbody
                mail.Body = message;

                //Convert pdfcontent from base64 string to byte array
                byte[] arrContent = Convert.FromBase64String(reportContent);

                //Create new stream from pdfcontent
                MemoryStream s = new MemoryStream(arrContent);
                //Set content type
                ContentType type = new ContentType(MediaTypeNames.Application.Pdf);
                //Create attachment
                Attachment attachment = new Attachment(s, type);
                attachment.ContentDisposition.FileName = template.AttachmentName;
                
                //Add to attachments
                mail.Attachments.Add(attachment);

                try
                {
                    smtp.Send(mail);
                }
                catch(SmtpException exc)
                {
                    //Add to list of non received
                    couldNotSendTo.Add(tutor.fornamn + " " + tutor.efternamn + ", " + tutor.aspnet_Membership.Email);

                    //Log error
                    LoggerCommon.LogNewEntry(
                    new LoggerCommon.LogNewEntryDelegate(Logger.LogNewEntry),
                    System.Reflection.MethodBase.GetCurrentMethod().Name, 
                    exc.ToString() + "\nSMTP Statuscode: " + exc.StatusCode.ToString(), 
                    (int)SurveyLoggingLevel.Error);
                }
            }

            ResponseStatus status = ResponseStatus.SUCCESS;
            if(couldNotSendTo.Count == tutors.Count)
            {
                status = ResponseStatus.SENT_TO_NONE;
            }
            else if(couldNotSendTo.Count > 0)
            {
                status = ResponseStatus.SENT_TO_SOME;
            }

            return new MailReportResponse { Status = status, NonReceived = couldNotSendTo };
        }
        
        //Initialize the smtp client
        private static SmtpClient InitializeSMTPClient(string smtpHost, int smtpPort, string smtpUser, string smtpPassword)
        {
            //SMTP-client for mailing
            SmtpClient smtp = new SmtpClient(smtpHost, smtpPort);
            System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(smtpUser, smtpPassword);
            smtp.Credentials = credentials;

            return smtp;
        }
        #endregion

        #region Generate PDF for comparison of selected courses in report list
        public static void CreateComparePDF(List<Models.PDFCompareCourses> CoursesToCompare)
        {
            //Lists that hold scale question texts and scale answers
            List<SurveyQuestionText> questions = new List<SurveyQuestionText>();
            List<Kurstillfalle> courses = new List<Kurstillfalle>();
            List<double> average = new List<double>(); //Kan tas bort sen
            string surveytype = CoursesToCompare[0].SurveyType;
            string surveyversion = CoursesToCompare[0].SurveyFormID;

            // Create a new PDF document
            Document document = new Document();
            document.Info.Title = "Kursjämförelse";
            document.Info.Subject = "Jämförelse mellan valda kurser";
            document.Info.Author = "Försvarshögskolan";

            //Set page format
            document.DefaultPageSetup.PageFormat = PageFormat.A4;
            document.DefaultPageSetup.LeftMargin = "2,5cm";
            document.DefaultPageSetup.RightMargin = "3cm";
            document.DefaultPageSetup.TopMargin = "3cm";
            document.DefaultPageSetup.BottomMargin = "3cm";

            //Add section (page) and paragraph to PDF
            Section sec = document.AddSection();
            Paragraph para = sec.AddParagraph();

            //Paragraph style
            para.Format.Alignment = ParagraphAlignment.Left;
            para.Format.Font.Name = defaultFontFamily;
            para.Format.Font.Size = defaultFontSize;
            para.Format.Font.Color = defaultFontColor;

            //Set PDF title
            if (surveytype == "0")
            {
                para.AddFormattedText("Kursjämförelse för kursenkäter del 1", new Font { Size = defaultHeading1FontSize, Bold = true, Color = headingColor });
                para.AddLineBreak();
                para.AddLineBreak();
                para.AddLineBreak();
            }
            else
            {
                para.AddFormattedText("Kursjämförelse för kursenkäter del 2", new Font { Size = defaultHeading1FontSize, Bold = true, Color = headingColor });
                para.AddLineBreak();
                para.AddLineBreak();
                para.AddLineBreak();
            }

            //Set survey version number
            para.AddFormattedText("Jämförelse mellan kurser som använt enkätversion: ", new Font { Size = defaultFontSize, Bold = true });
            para.AddText(surveyversion);
            para.AddLineBreak();

            //Set survey version creation date
            int surveyformid = Convert.ToInt16(CoursesToCompare[0].SurveyFormID);
            string date;
            using (var db = new UL360Entities())
            {
                date = db.SurveyForms.Where(f => f.SurveyFormId == surveyformid).First().DateCreated.ToShortDateString();
            }
            para.AddFormattedText("Enkäten skapades den: ", new Font { Size = defaultFontSize, Bold = true });
            para.AddText(date);
            para.AddLineBreak();

            //Set creation date for comparison report
            para.AddFormattedText("Rapport uthämtad den: ", new Font { Size = defaultFontSize, Bold = true });
            para.AddText(DateTime.Now.ToShortDateString());
            para.AddLineBreak();


            //Add footer to PDF's first page
            if (surveytype == "0")
            {
                Paragraph footer = sec.AddParagraph();
                footer.AddText("Försvarshögskolan · Rapport kursjämförelse del 1 · Tel 054-10 40 45");
                footer.Format.Alignment = ParagraphAlignment.Center;
                footer.Format.SpaceBefore = Unit.FromCentimeter(19.5);
            }
            else
            {
                Paragraph footer = sec.AddParagraph();
                footer.AddText("Försvarshögskolan · Rapport kursjämförelse del 2 · Tel 054-10 40 45");
                footer.Format.Alignment = ParagraphAlignment.Center;
                footer.Format.SpaceBefore = Unit.FromCentimeter(19.5);
            }

            //For each course in compare list add course data and scale question texts to lists
            foreach (Models.PDFCompareCourses course in CoursesToCompare)
            {
                int courseId = Convert.ToInt16(course.CourseID);
                int formId = Convert.ToInt16(course.SurveyFormID);

                using (var db = new UL360Entities())
                {
                    //Get courses
                    courses.AddRange(db.Kurstillfalles.Where(c => c.kursid == courseId).DefaultIfEmpty(null).ToList());

                    //Get questions texts for form id and question type
                    questions = db.SurveyForms.Where(f => f.SurveyFormId == formId).SelectMany(fq => fq.SurveyQuestions).OrderBy(q => q.Order).Where(type => type.QuestionType == 0).SelectMany(qt => qt.SurveyQuestionTexts).Where(l => l.fk_SprakId == 1).ToList();
                }
            }

            //Add new section to PDF (new page)
            sec = document.AddSection();

            //Int variable to hold current question number
            int i = 1;

            //Get answer values and calculate the average value per course for each question
            foreach (SurveyQuestionText q in questions)
            {
                //Int variable to hold current cell number
                int n = 2;
                //Int variable to hold number of courses when iterating through the courses
                int c = 0;

                //Int variable to hold current scale question id
                int questionId = q.fk_SurveyQuestionId;

                // Add a single paragraph to PDF
                para = sec.AddParagraph();

                //Add question text to PDF
                para.AddFormattedText(i.ToString() + ". " + q.Question, new Font { Size = defaultHeading3FontSize, Bold = true });
                para.AddLineBreak();
                para.AddLineBreak();

                // Create table for presenting courses and average values in PDF
                Table table = new Table();
                
                //Add table column to PDF
                Column col1 = table.AddColumn();
                Column col2 = table.AddColumn();
                col1.Borders.Bottom = new Border { Color = Colors.LightGray, Width = 1 };
                col1.Borders.Right = new Border { Color = Colors.LightGray, Width = 1 };
                col2.Borders.Bottom = new Border { Color = Colors.LightGray, Width = 1 };

                foreach (Kurstillfalle k in courses)
                {
                    int courseId = k.kursid;

                    using (var db = new UL360Entities())
                    {
                        List<SurveyAnswerScale> ScaleAnswer = db.SurveyAnswerScales.Where(s => s.fk_KursId == courseId && s.fk_SurveyQuestionId == questionId).ToList();
                        List<int> AnswerList = new List<int>();

                        //Add each course answer for thsi particular question into a list
                        foreach (SurveyAnswerScale s in ScaleAnswer)
                        {
                            //If an answer is 0 = don't know then it will not count
                            if (s.ScaleAnswer > 0)
                            {
                                AnswerList.Add(s.ScaleAnswer);
                            }
                        }

                        //Sum an count and calculate the average value for the course and question and add the average value to a list
                        double sum = AnswerList.Sum();
                        double numberOf = AnswerList.Count();
                        double averageValue = Math.Round((sum / numberOf), 2);

                        //Add average value for course and question id to average list
                        average.Add(averageValue);

                    }
                }

                //Int variable to hold number when iterating through the average values
                int a = average.Count() - courses.Count();

                //Add row and row style
                Row row = table.AddRow();

                //Add text to table rows first cells in PDF
                row.Cells[0].AddParagraph().AddFormattedText("Kurs", new Font { Bold = true });
                row.Cells[1].AddParagraph().AddFormattedText("Medelvärde", new Font { Bold = true });

                //Add course name and average value per question to PDF
                foreach (Kurstillfalle kt in courses)
                {
                    //Add course name for scale question to PDF
                    Row trow = table.AddRow();
                    trow.Cells[0].AddParagraph(courses[c].organisation.ToString());

                    //Add course average for scale question to PDF
                    if (a < 0)
                    {
                        a = 0;
                        if (double.IsNaN(average[a]))
                        {
                            trow.Cells[1].AddParagraph("Inga svar");
                        }
                        else
                        {
                            //Mark average value with red if below 6
                            if (average[a] < 6)
                            {
                                trow.Cells[1].AddParagraph().AddFormattedText(average[a].ToString(), new Font { Color = Colors.Red, Bold = true });
                            }
                            else
                            {
                                trow.Cells[1].AddParagraph(average[a].ToString());
                            }
                        }
                    }
                    else
                    {
                        if (double.IsNaN(average[a]))
                        {
                            trow.Cells[1].AddParagraph("Inga svar");
                        }
                        else
                        {
                            //Mark average value with red if below 6
                            if (average[a] < 6)
                            {
                                trow.Cells[1].AddParagraph().AddFormattedText(average[a].ToString(), new Font { Color = Colors.Red, Bold = true });
                            }
                            else
                            {
                                trow.Cells[1].AddParagraph(average[a].ToString());
                            }
                        }
                    }

                    n++;
                    c++;
                    a++;
                }

                //Add table to PDF
                sec.Add(table);

                //Add new paragraph to PDF
                para = sec.AddParagraph();
                para.AddLineBreak();
                para.AddLineBreak();

                //Iterate question number
                i++;
            }

            //Render document
            PdfDocumentRenderer renderer = new PdfDocumentRenderer(true, PdfFontEmbedding.Always);
            renderer.Document = document;
            renderer.RenderDocument();

            // Send PDF to browser
            MemoryStream stream = new MemoryStream();
            renderer.PdfDocument.Save(stream, false);
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ContentType = "application/pdf";
            HttpContext.Current.Response.AddHeader("content-length", stream.Length.ToString());
            HttpContext.Current.Response.BinaryWrite(stream.ToArray());
            HttpContext.Current.Response.Flush();
            stream.Close();
            HttpContext.Current.Response.End();
        }
        #endregion
    } 
}